﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Linq;
using WMS.FC.Domain.DomainObject.System;
using WMS.FC.Domain.PersistenceObject.Business;
using WMS.FC.Domain.Repository;
using WMS.FC.Domain.Service.System;
using WMS.FC.Domain.Repository;
using WMS.FC.Domain.Service.Location.Interface;
using WMS.FC.Domain.Service.System;
using WMS.FC.Domain.Service.Tasks.Interface;
using WMS.FC.Domain.Service.Technology.Interface;
using WMS.FC.Domain.Service.Tray.Interface;

namespace WMS.FC.Domain.Service.Tasks
{
    public class ChangeTaskStateService : ServiceBase, IChangeTaskStateService
    {
        protected readonly ITaskRepository taskRepository;
        protected readonly ILocationRepository locationRepository;
        protected readonly IGetTrayInfoService getTrayInfoService;
        protected readonly ITechnologyRepository technologyRepository;
        protected readonly IChangeTrayTechnologyService changeTrayTechnologyService;
        protected readonly List<string> InboundTaskType = new List<string>()
        {
            "TaskType_Inbound",
            "TaskType_ManualIn",
            "TaskType_ToolIn",
        };

        protected readonly List<string> OutboundTaskType = new List<string>()
        {
            "TaskType_Outbound",
            "TaskType_ManualOut",
            "TaskType_ToolOut",
            "TaskType_FireOut",
            "TaskType_ExceptionOut",
        };

        protected readonly List<string> TransferTaskType = new List<string>()
        {
            "TaskType_Transfer",
            "TaskType_ManualTransfer",
            "TaskType_ToolTransfer",
        };

        public ChangeTaskStateService(
            ILogger<ServiceBase> logger,
            IOptions<WmsSettings> options,
            IMapper mapper,
            ITaskRepository taskRepository,
            ILocationRepository locationRepository,
            IGetTrayInfoService getTrayInfoService,
            ITechnologyRepository technologyRepository,
            IChangeTrayTechnologyService changeTrayTechnologyService)
            : base(logger, options, mapper)
        {
            this.taskRepository = taskRepository;
            this.locationRepository = locationRepository;
            this.getTrayInfoService = getTrayInfoService;
            this.technologyRepository = technologyRepository;
            this.changeTrayTechnologyService = changeTrayTechnologyService;
        }

        public async Task<ActionResultBase> ChangeTaskState(string? taskCode, string? taskStateCode, UserInfo userInfo)
        {
            var result = new ActionResultBase("变更任务状态");
            try
            {
                if (string.IsNullOrWhiteSpace(taskCode))
                    return result.ArgumentError("任务编码不能为空");

                if (string.IsNullOrWhiteSpace(taskStateCode))
                    return result.ArgumentError("任务状态不能为空");

                var taskPO = await taskRepository.GetTaskByTaskCode(taskCode);
                if (taskPO == null)
                    return result.ArgumentError($"任务编码:({taskCode}),任务数据未找到");

                switch (taskStateCode)
                {
                    case "TaskState_WaitingExecute":
                        return await ChangeTaskStateToWaiting(taskPO, userInfo);
                    case "TaskState_Executing":
                        return await ChangeTaskStateToExecuting(taskPO, userInfo);
                    case "TaskState_PartExecuted":
                        return await ChangeTaskStateToPartExecuted(taskPO, userInfo);
                    case "TaskState_Executed":
                        return await ChangeTaskStateToExecuted(taskPO, userInfo);
                    case "TaskState_Rollbacked":
                        return await ChangeTaskStateToRollbacked(taskPO, userInfo);
                }
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }

        protected async Task<ActionResultBase> ChangeTaskStateToWaiting(TaskPO task, UserInfo userInfo)
        {
            var result = new ActionResultBase("变更任务状态为待执行");
            try
            {
                if (task.StateCode != "TaskState_Executing")
                    return result.BusinessError("当前任务状态不是执行中");

                task.StateCode = "TaskState_WaitingExecute";
                var count = await taskRepository.Update(task, userInfo);
                if (count == 0)
                    return result.DbError("更新任务状态异常");
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }

        protected async Task<ActionResultBase> ChangeTaskStateToExecuting(TaskPO task, UserInfo userInfo)
        {
            var result = new ActionResultBase("变更任务状态为执行中");
            try
            {
                if (task.StateCode != "TaskState_WaitingExecute")
                    return result.BusinessError("当前任务状态不是待执行");

                task.StateCode = "TaskState_Executing";
                task.StartTime = DateTime.Now;
                var count = await taskRepository.Update(task, userInfo);
                if (count == 0)
                    return result.DbError("更新任务状态异常");
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }

        protected async Task<ActionResultBase> ChangeTaskStateToPartExecuted(TaskPO task, UserInfo userInfo)
        {
            var result = new ActionResultBase("变更任务状态为部分完成");
            try
            {
                if (!OutboundTaskType.Contains(task.TypeCode))
                    return result.BusinessError("只有出库任务可以变更为部分完成状态");

                if (task.StateCode != "TaskState_Executing")
                    return result.BusinessError("当前任务状态不是执行中");

                task.StateCode = "TaskState_PartExecuted";
                var count = await taskRepository.Update(task, userInfo);
                if (count == 0)
                    return result.DbError("更新任务状态异常");
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }

        protected async Task<ActionResultBase> ChangeTaskStateToExecuted(TaskPO task, UserInfo userInfo)
        {
            var result = new ActionResultBase("变更任务状态为已完成");
            try
            {
                if (task.StateCode != "TaskState_Executing" && task.StateCode != "TaskState_PartExecuted")
                    return result.BusinessError("当前任务状态不是执行中或部分完成");

                var getTrayInfoResult = await getTrayInfoService.GetTrayInfo(task.TrayBarcode1, false, false, false, false, true, true, userInfo);
                if (!getTrayInfoResult.IsSuccess)
                    return result.Fail(getTrayInfoResult);

                var trayDO = getTrayInfoResult.Data!;
                var nextTechnologyRouteProcessPO = trayDO.TechnologyRouteProcessList!
                        .FirstOrDefault(technologyRouteProcess => technologyRouteProcess.StateCode == "TechnologyState_Enabled" && technologyRouteProcess.SortNumber > trayDO.CurrentTechnologyRouteProcess!.SortNumber);

                if (nextTechnologyRouteProcessPO == null)
                    nextTechnologyRouteProcessPO = trayDO.CurrentTechnologyRouteProcess;

                var count = 0;
                if (InboundTaskType.Contains(task.TypeCode))
                {
                    var locationPO = await locationRepository.GetLocationByCode(task.EndPointCode);
                    if (locationPO == null)
                        return result.BusinessError($"货位编码:({task.EndPointCode}),货位数据未找到");

                    if (!trayDO.CurrentTechnologyRouteProcess!.AgingTime.HasValue)
                        return result.BusinessError($"托盘条码:({trayDO.CurrentTray.Barcode}),工艺路径:({trayDO.CurrentTray.TechnologyRouteCode}),工艺工序:({trayDO.CurrentTray.TechnologyProcessCode}),未设置静置时间");

                    var OutboundTargetStation = "";
                    if (trayDO.CurrentTray.TechnologyRouteCode != options.Value.EmptyTrayTechnologyRoute)
                    {
                        var technologyProcessRoute = await technologyRepository.GetLineTechnologyProcessRoute(task.LineCode, nextTechnologyRouteProcessPO!.TechnologyProcessCode);
                        if (technologyProcessRoute == null)
                            return result.BusinessError($"产线:({task.LineCode}),工艺工序:({nextTechnologyRouteProcessPO!.TechnologyProcessCode}),工艺工序路径未设置");

                        OutboundTargetStation = technologyProcessRoute.StationCode;
                    }

                    locationPO.ContainerBarcode = task.ContainerBarcode;
                    locationPO.TrayBarcode1 = task.TrayBarcode1;
                    locationPO.TrayBarcode2 = task.TrayBarcode2;
                    locationPO.TrayBarcode3 = task.TrayBarcode3;
                    locationPO.TotalCellCount = task.TotalCellCount;
                    locationPO.MaterialCode = task.MaterialCode;
                    locationPO.TechnologyRouteCode = task.TechnologyRouteCode;
                    locationPO.TechnologyProcessCode = task.TechnologyProcessCode;
                    locationPO.OutboundTargetStation = OutboundTargetStation;
                    locationPO.TechnologyAgingTime = trayDO.CurrentTechnologyRouteProcess!.AgingTime.ToString();
                    locationPO.ActualAgingTime = trayDO.CurrentTechnologyRouteProcess!.AgingTime;
                    locationPO.InboundTime = DateTime.Now;
                    locationPO.OutStateCode = null;
                    locationPO.Message += ";完成入库任务";

                    count = await locationRepository.Update(locationPO, userInfo);
                    if (count == 0)
                        return result.DbError($"货位编号:({task.EndPointCode}),更新货位状态异常");
                }
                else if (OutboundTaskType.Contains(task.TypeCode))
                {
                    var locationPO = await locationRepository.GetLocationByCode(task.StartPointCdoe);
                    if (locationPO == null)
                        return result.BusinessError($"货位编码:({task.StartPointCdoe}),货位数据未找到");

                    locationPO.ContainerBarcode = null;
                    locationPO.TrayBarcode1 = null;
                    locationPO.TrayBarcode2 = null;
                    locationPO.TrayBarcode3 = null;
                    locationPO.TotalCellCount = null;
                    locationPO.MaterialCode = null;
                    locationPO.TechnologyRouteCode = null;
                    locationPO.TechnologyProcessCode = null;
                    locationPO.OutboundTargetStation = null;
                    locationPO.TechnologyAgingTime = null;
                    locationPO.ActualAgingTime = null;
                    locationPO.InboundTime = null;
                    locationPO.OutStateCode = null;
                    locationPO.LastOutboundTime = DateTime.Now;
                    locationPO.Message += ";完成出库任务";

                    count = await locationRepository.Update(locationPO, userInfo);
                    if (count == 0)
                        return result.DbError($"货位编号:({task.StartPointCdoe}),更新货位状态异常");

                    var changeTrayTechnologyResult = await changeTrayTechnologyService.ChangeTrayTechnology(trayDO.CurrentTray.Barcode, nextTechnologyRouteProcessPO!.TechnologyRouteCode, nextTechnologyRouteProcessPO!.TechnologyProcessCode, userInfo);
                    if (!changeTrayTechnologyResult.IsSuccess)
                        return result.Fail(changeTrayTechnologyResult);
                }
                else if (TransferTaskType.Contains(task.TypeCode))
                {

                }

                count = await taskRepository.Delete(task);
                if (count == 0)
                    return result.DbError($"任务编码:({task.Code}),删除任务异常");
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }

        protected async Task<ActionResultBase> ChangeTaskStateToRollbacked(TaskPO task, UserInfo userInfo)
        {
            var result = new ActionResultBase("变更任务状态为已回收");
            try
            {
                if (task.StateCode != "TaskState_WaitingExecute" && task.StateCode != "TaskState_Executing")
                    return result.BusinessError("当前任务状态不是待执行或执行中");

                var count = 0;
                if (InboundTaskType.Contains(task.TypeCode))
                {
                    var locationPO = await locationRepository.GetLocationByCode(task.EndPointCode);
                    if (locationPO == null)
                        return result.BusinessError($"货位编码:({task.EndPointCode}),货位数据未找到");

                    locationPO.StateCode = "LocationState_Empty";
                    locationPO.Message += ";回收入库任务";

                    count = await locationRepository.Update(locationPO, userInfo);
                    if (count == 0)
                        return result.DbError($"货位编号:({task.EndPointCode}),更新货位状态异常");
                }
                else if (OutboundTaskType.Contains(task.TypeCode))
                {
                    var locationPO = await locationRepository.GetLocationByCode(task.StartPointCdoe);
                    if (locationPO == null)
                        return result.BusinessError($"货位编码:({task.StartPointCdoe}),货位数据未找到");

                    locationPO.StateCode = "LocationState_Stored";
                    locationPO.Message += ";回收出库任务";

                    count = await locationRepository.Update(locationPO, userInfo);
                    if (count == 0)
                        return result.DbError($"货位编号:({task.StartPointCdoe}),更新货位状态异常");
                }
                else if (TransferTaskType.Contains(task.TypeCode))
                {
                    var locationPO = await locationRepository.GetLocationByCode(task.StartPointCdoe);
                    if (locationPO == null)
                        return result.BusinessError($"货位编码:({task.StartPointCdoe}),货位数据未找到");

                    locationPO.StateCode = "LocationState_Stored";
                    locationPO.Message += ";回收移库任务";

                    count = await locationRepository.Update(locationPO, userInfo);
                    if (count == 0)
                        return result.DbError($"货位编号:({task.StartPointCdoe}),更新货位状态异常");

                    locationPO = await locationRepository.GetLocationByCode(task.EndPointCode);
                    if (locationPO == null)
                        return result.BusinessError($"货位编码:({task.EndPointCode}),货位数据未找到");

                    locationPO.StateCode = "LocationState_Empty";
                    locationPO.Message += ";回收移库任务";

                    count = await locationRepository.Update(locationPO, userInfo);
                    if (count == 0)
                        return result.DbError($"货位编号:({task.EndPointCode}),更新货位状态异常");
                }

                count = await taskRepository.Delete(task);
                if (count == 0)
                    return result.DbError($"任务编码:({task.Code}),删除任务异常");
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;

        }
        //public class ChangeTaskStateService : ServiceBase, IChangeTaskStateService
        //{
        //    protected readonly ITaskRepository taskRepository;
        //    public ChangeTaskStateService(
        //        ILogger<ServiceBase> logger,
        //        IOptions<WmsSettings> options,
        //        IMapper mapper,
        //        ITaskRepository taskRepository)
        //        : base(logger, options, mapper)
        //    {
        //        this.taskRepository = taskRepository;
        //    }
        //    public async Task<ActionResultBase> ChangeTaskState(string taskCode, string taskStateCode, UserInfo userInfo)
        //    {
        //        var result = new ActionResultBase("变更WMS任务状态");
        //        try
        //        {
        //            if (string.IsNullOrWhiteSpace(taskCode))
        //                return result.ArgumentError("任务编码不能为空");

        //            if (string.IsNullOrWhiteSpace(taskStateCode))
        //                return result.ArgumentError("任务状态不能为空");

        //            var taskEntity = await taskRepository.GetTaskByTaskCode(taskCode);
        //            if (taskEntity == null)
        //                return result.BusinessError($"任务:{taskCode},数据丢失");

        //            if (taskEntity.StateCode == taskStateCode)
        //                return result.BusinessError($"当前任务状态已经是{taskStateCode}");
        //        }
        //        catch (Exception ex)
        //        {
        //            return result.Exception(ex);
        //        }
        //        return result;
        //    }
        //}
    }
}
